/**
 * JAVACC DEMO 1.0
 */
package com.apache.rpc.controller;

import com.apache.api.api.ApiService;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.api.vo.ResultMsg;
import com.apache.database.constant.SpringContextLoader;
import com.apache.rpc.common.JsonEntityParese;
import com.apache.rpc.common.RpcUtil;
import com.apache.rpc.common.XMLMapParse;
import com.apache.tools.RequestTools;
import com.apache.tools.StrUtil;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * description: Http或Https访问action
 *
 * @author ius 创建时间：2016-12-17
 */
@Controller
public class RestfullRPCAction {

    private Logger log = Logger.getLogger("restful");

    @Autowired
    private ApiService rpcService;

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @RequestMapping(value = "/rpc/service/doService.action", method = RequestMethod.POST)
    public void doService(HttpServletRequest request, HttpServletResponse response) {
        sendMessage(request, response);
    }

    /**
     * description:  系统统一接口(restfull--post)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @RequestMapping(value = "/rpc/service/doService", method = RequestMethod.POST)
    public void doServiceForRf(HttpServletRequest request, HttpServletResponse response) {
        sendMessage(request, response);
    }

    /**
     * description:  系统统一接口(restfull--get)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @RequestMapping(value = "/rpc/service/doService", method = RequestMethod.GET)
    public void serviceForRf(HttpServletRequest request, HttpServletResponse response) {
        sendMessage(request, response);
    }

    private void sendMessage(HttpServletRequest request, HttpServletResponse response) {
        ParamsVo vo = new ParamsVo();
        String reqMsg = null;
        try {
            reqMsg = IOUtils.toString(request.getInputStream(), "UTF-8");//以流的方式传参
        } catch (IOException e) {
            e.printStackTrace();
        }
        String beanId = "";
        if (StrUtil.isNull(reqMsg)) {//xml参数
            String paramStr = request.getParameter("params");
            if (StrUtil.isNotNull(paramStr)) {
                Map<String, Object> headMap = new HashMap<String, Object>();
                Map<String, Object> bodyMap = new HashMap<String, Object>();
                XMLMapParse.instance().xmlGetData(paramStr, headMap, bodyMap);
                vo.setMethodKey(headMap.get("MethodCode").toString());
                vo.setParams(bodyMap);
                beanId = String.valueOf(headMap.get("BeanId"));
            } else {
                String methodCode = request.getParameter("MethodCode");
                Map<String, Object> bodyMap = getRequestParam(request);
                vo.setMethodKey(methodCode);
                vo.setParams(bodyMap);
                beanId = request.getParameter("BeanId");
            }
        }else{
            Map<String, Object> headMap = new HashMap<String, Object>();
            Map<String, Object> bodyMap = new HashMap<String, Object>();
            XMLMapParse.instance().xmlGetData(reqMsg, headMap, bodyMap);
            vo.setMethodKey(headMap.get("MethodCode").toString());
            vo.setParams(bodyMap);
            beanId = String.valueOf(headMap.get("BeanId"));
        }
        vo.setParams("requestIp", RequestTools.getIp(request));
        getResultInfo(vo, request, response, beanId);
    }

    private void getResultInfo(ParamsVo vo, HttpServletRequest request,
            HttpServletResponse response, String beanId) {
        String result = "";
        try {
            ResultEntity entity = null;
            if (StrUtil.isNull(beanId) || "rpcService".equalsIgnoreCase(beanId)) {
                entity = rpcService.doService(vo);
            } else {
                ApiService service = (ApiService) SpringContextLoader.getBean(beanId);
                entity = service.doService(vo);
            }
            if (StrUtil.isEmpty(entity)) {
                entity = new ResultEntity();
                entity.setResult("false");
                entity.setMessage("接口调用失败！");
            }
            String callback = request.getParameter("callback");
            if (StrUtil.isNull(callback)) {
                String paramType = request.getParameter("ParamType");
                if ("json".equalsIgnoreCase(paramType))
                    result = JsonEntityParese.instance().beanToJson(entity);
                else
                    result = JsonEntityParese.instance().toXml(entity);
                response.setContentType("text/html; charset=UTF-8");
                PrintWriter out = response.getWriter();
                out.print(result);
                out.flush();
            } else {///支持jsonp数据格式
                PrintWriter out = response.getWriter();
                response.setContentType("application/javascript");
                if (RpcUtil.isEmpty(entity.getEntity())) {
                    ResultMsg msg = new ResultMsg("F", "操作失败");
                    JSONObject json = JSONObject.fromObject(msg);
                    result = json.toString();
                } else {
                    JSONObject json = JSONObject.fromObject(entity);
                    result = json.toString();
                }
                out.print(callback + "(" + result + ")");
                out.flush();
            }
        } catch (Exception e) {
            log.error("请求出错：" + e.getMessage());
        }
    }

    private Map<String, Object> getRequestParam(HttpServletRequest request) {
        Map<String, Object> bodyMap = new HashMap<String, Object>();
        Set keSet = request.getParameterMap().entrySet();
        for (Iterator itr = keSet.iterator(); itr.hasNext(); ) {
            Map.Entry me = (Map.Entry) itr.next();
            String ok = String.valueOf(me.getKey());
            if ("ParamType".equals(ok) || "callback".equals(ok) || "MethodCode".equals(ok))
                continue;
            Object ov = me.getValue();
            String[] value = new String[1];
            if (ov instanceof String[]) {
                value = (String[]) ov;
            } else {
                value[0] = ov.toString();
            }
            if (value.length > 0) {
                bodyMap.put(ok.toString(), value[0]);
                request.setAttribute(ok.toString(), value[0]);
            }
        }
        return bodyMap;
    }
}
